# ----------------------------------------------------------------------------
#       Copyright (C) 2013-2014 Huynh Vi Lam  <domovilam@gmail.com>
#
#       This file is part of pimucha.
#
#	This program is free software: you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation, either version 3 of the License, or
#	(at your option) any later version.
#	
#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#	
#	You should have received a copy of the GNU General Public License
#	along with this program.  If not, see <http://www.gnu.org/licenses/>.
# ----------------------------------------------------------------------------

import logging,sys,time
from piHAlibs import (adstr2addr,serverthreads)
from .corelibs import (chksetup,chkcmdname)
from .controller import CONTROLLER
from .decoders import (addparser,adddecoder)
from .netcontroller import NETCONTROLLER
from .rpccmds import RPCFunctions
from .rpclcmds import RPCLocalFunctions
from .servers import (PortInUse,Servers,SetupDaemons,SetupControllers)

logger = logging.getLogger()



def setupctrl(param):
    """
    param = [name,idctrl,port]
    name  = first position
    idctrl = second position
    port = needed for serial
          needed for USB if many controllers of same type
    """
    p = chksetup(param,SetupDaemons)
    if not p:
        return False
    name,idctrl,port,rxtx = p
    namedev = name + ':' + idctrl
    #Check if a previous thread of same controller is alive
    tt = serverthreads(namedev)
    if tt:
        if tt.isAlive():
            logger.error('A controller thread is already started with this name %s',namedev)
            return False
    if port == 'Defaults' : 
        port = None
    if port in PortInUse:
        if idctrl in PortInUse[port]:
            logger.error('The same port %s is already setup with %s ',port,PortInUse[port])
            return False
    if namedev in SetupControllers:
        logger.error('A controller is already setup with %s',namedev)
        return False
    #Init class object
    try:
        dev = CONTROLLER(idctrl,port)
        dev.name = name
    except Exception as e:
        logger.critical("%s : %s", repr(e.__class__), str(e))
        logger.error('Error in init class object for %s',repr(param))
        return False
    #Setup daemon
    try:
        dev.tsetup()
    except Exception as e:
        logger.critical("%s : %s", repr(e.__class__), str(e))
        logger.error('Error in setup daemon %s',repr(param))
        return False
    if dev.setup:
        logger.warning('Daemon of Controller correctly setup : %s',repr(dev))
        return True
    else:
        logger.error('Error in setup Daemon of Controller %s',repr(param))
        return False


def setupnetctrl(param):
    """
    param = [name,idctrl-rxtx,port]
    name  = first position
    idctrl-rxtx = second position
          idcontroller '-' rxtx
          rxtx in ['RX','TX']
    port = host:port
    """
    p = chksetup(param,SetupDaemons)
    if not p:
        return False
    name,idctrl,port, rxtx = p
    if (rxtx is None) or (port == 'Defaults'):
        logger.error('Syntax error with the parameter')
        return False
    addr = adstr2addr(port)
    if addr in PortInUse:
        logger.error('The same address:port %s is already setup with %s ',port,PortInUse[addr])
        return False
    namedev = name + ':' + idctrl
    if namedev in SetupControllers:
        logger.error('A netcontroller is already setup with %s',namedev)
        return False
    if rxtx == 'RX':
        rx = True
    else:
        rx = False
    #Init class object
    try:
        dev = NETCONTROLLER(idctrl,addr=addr,RX=rx)
        dev.name = name
    except Exception as e:
        logger.critical("%s : %s", repr(e.__class__), str(e))
        logger.error('Error in init class object for %s',param)
        return False
    #Setup daemon
    try:
        dev.tsetup()
    except Exception as e:
        logger.critical("%s : %s", repr(e.__class__), str(e))
        logger.error('Error in setup daemon %s',param)
        return False
    if dev.setup:
        logger.warning('Daemon of NETController correctly setup : %s',repr(dev))
        return True
    else:
        logger.error('Error in setup Daemon of NETController %s',param)
        return False


def setupsrv(param):
    """
    param = [name,server,port]
    name  = first position
    server = second position
    port = third position host:port
    """
    p = chksetup(param,SetupDaemons)
    if not p:
        return False
    name,server,port,rxtx = p
    if port != 'Defaults' : 
        if port in PortInUse:
            logger.error('The same address:port %s is already setup with %s ',port,PortInUse[port])
            return False
    if server not in ['RPCS','TCPRX','TCPS']:
        logger.error('Syntax error for the type of server to setup')
        return False
    namesrv = name + ':' + server
    if port == 'Defaults':
        addr = None
    else:
        addr = adstr2addr(port)
    #Init class object
    try:
        srv = Servers[server](addr)
        srv.name = namesrv
    except Exception as e:
        logger.critical("%s : %s", repr(e.__class__), str(e))
        logger.error('Error in init class object for %s',param)
        return False
    if server == 'RPCS':
        srv.Functions += RPCFunctions
        if port == 'Defaults': srv.Functions += RPCLocalFunctions
    #Setup daemon
    try:
        srv.tsetup()
    except Exception as e:
        logger.critical("%s : %s", repr(e.__class__), str(e))
        logger.error('Error in setup daemon %s',param)
        return False
    if srv.setup:
        PortInUse.setdefault(port)
        PortInUse[port] = namesrv
        SetupDaemons.setdefault(namesrv)
        SetupDaemons[namesrv] = srv
        logger.warning('Daemon of server correctly setup : %s',repr(srv))
        return True
    else:
        logger.error('Error in setup Daemon of server %s',param)
        return False


def startsrv(param):
    p = chkcmdname(param,SetupDaemons)	#p = [cmd,name,dev]
    if not p:
        return False
    cmd, name, dev = p
    tt = serverthreads(name)
    if tt:
        logger.warning('An instance %s of %s is already active' , tt.name,name)
        return False
    else:
        try:
            cmd()
        except Exception as e:
            logger.critical("%s : %s", repr(e.__class__), str(e))
            logger.error('Unable to execute %s',repr(cmd))
            return False
    logger.info('Command started for %s',param)
    return True


def stopsrv(param):
    if isinstance(param,list):
        namectrl = param[0]
    else:
        namectrl = param
    if namectrl == 'SYSLOGF':
        SetupDaemons['INParser'].stops()
        SetupDaemons['SYSLOGF'].stops()
        del SetupDaemons['SYSLOGF']
        del SetupDaemons['INParser']
        return True
    tt = serverthreads(namectrl)
    if tt:
        SetupDaemons[namectrl].stops()
        tt.join(5)
        if not tt.isAlive():
            logger.info('The thread instance %s is stopped.',tt.name)
            del SetupDaemons[namectrl]
            if namectrl.split(':')[1] in ['RPCS','TCPRX','TCPS']: del PortInUse[namectrl]
        return True
    if namectrl in SetupDaemons:
        logger.info('Clean memory for %s', namectrl)
        SetupDaemons[namectrl].cleanm()
        return True
    logger.info('No thread instance for %s', namectrl)
    return False


def stopallctrls():
    SC = list(SetupControllers.keys())
    for ctrl in SC:
        stopsrv(SetupControllers[ctrl].namedev)
